// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	9/15/2014 3:54:57 PM				
// -----------------------------

#ifndef _LuaScript_inl
#define _LuaScript_inl

namespace ObjectLua
{
	
		/*
		//	Call a Function in the Script
		//	1 Arguments, no return
		*/
		template<typename P0>
		void LuaScript::callFunction(const char* name, P0 arg1)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);

			LuaDataType<P0>::push(m_lpLua, arg1);

			m_lpLua->getStack()->pcall(1, 0);
		}
		/*
		//	Call a Function in the Script
		//	2 Arguments, no return
		*/
		template<typename P0, typename P1>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);

			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);

			m_lpLua->getStack()->pcall(2, 0);
		}
		/*
		//	Call a Function in the Script
		//	3 Arguments, no return
		*/
		template<typename P0, typename P1, typename P2>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2, P2 arg3)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);

			m_lpLua->getStack()->pcall(3, 0);
		}
		/*
		//	Call a Function in the Script
		//	4 Arguments, no return
		*/
		template<typename P0, typename P1, typename P2, typename P3>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);

			m_lpLua->getStack()->pcall(4, 0);
		}
		/*
		//	Call a Function in the Script
		//	5 Arguments, no return
		*/
		template<typename P0, typename P1, typename P2, typename P3, typename P4>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);

			m_lpLua->getStack()->pcall(5, 0);
		}
		/*
		//	Call a Function in the Script
		//	6 Arguments, no return
		*/
		template<typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5, P5 arg6)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);
			LuaDataType<P5>::push(m_lpLua, arg6);

			m_lpLua->getStack()->pcall(6, 0);
		}
		/*
		//	Call a Function in the Script
		//	7 Arguments, no return
		*/
		template<typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		void LuaScript::callFunction(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5, P5 arg6, P6 arg7)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);
			LuaDataType<P5>::push(m_lpLua, arg6);
			LuaDataType<P6>::push(m_lpLua, arg7);

			m_lpLua->getStack()->pcall(7, 0);
		}
		



		/*
		//	Call a Function in the Script
		//	0 Arguments, return
		*/
		template<typename R>
		R LuaScript::callFunctionR(const char* name)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);

			m_lpLua->getStack()->pcall(0, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	1 Arguments, return
		*/
		template<typename R, typename P0>
		R LuaScript::callFunctionR(const char* name, P0 arg1)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);

			LuaDataType<P0>::push(m_lpLua, arg1);

			m_lpLua->getStack()->pcall(1, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	2 Arguments, return
		*/
		template<typename R, typename P0, typename P1>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);

			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);

			m_lpLua->getStack()->pcall(2, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	3 Arguments, return
		*/
		template<typename R, typename P0, typename P1, typename P2>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2, P2 arg3)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);

			m_lpLua->getStack()->pcall(3, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	4 Arguments, return
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);

			m_lpLua->getStack()->pcall(4, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	5 Arguments, return
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);

			m_lpLua->getStack()->pcall(5, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	6 Arguments, return
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5, P5 arg6)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);
			LuaDataType<P5>::push(m_lpLua, arg6);

			m_lpLua->getStack()->pcall(6, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
		/*
		//	Call a Function in the Script
		//	7 Arguments, return
		*/
		template<typename R, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
		R LuaScript::callFunctionR(const char* name, P0 arg1, P1 arg2, P2 arg3, P3 arg4, P4 arg5, P5 arg6, P6 arg7)
		{
			LuaStackGuard stackGuard(m_lpLua);
			m_Ref.push();
			m_lpLua->getStack()->getupvalue(-1, 1);

			m_lpLua->getStack()->getField(-1, name);
			
			LuaDataType<P0>::push(m_lpLua, arg1);
			LuaDataType<P1>::push(m_lpLua, arg2);
			LuaDataType<P2>::push(m_lpLua, arg3);
			LuaDataType<P3>::push(m_lpLua, arg4);
			LuaDataType<P4>::push(m_lpLua, arg5);
			LuaDataType<P5>::push(m_lpLua, arg6);
			LuaDataType<P6>::push(m_lpLua, arg7);

			m_lpLua->getStack()->pcall(7, 1);

			return LuaDataType<R>::get(m_lpLua, -1);
		}
}

#endif